package com.example.vm.service.impl;

import com.common.constant.RedisConstant;
import com.common.utils.RedisUtils;
import com.example.api.domain.entity.User;
import com.example.vm.domain.entity.Video;
import com.example.vm.service.InterestPushService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
public class InterestPushServiceImpl implements InterestPushService {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private RedisUtils redisUtils;
    @Override
    public Set<Long> pushByTypeId(Long typeId) {
        List<Object> videos = redisTemplate.opsForSet().randomMembers(RedisConstant.SYSTEM_TYPE_VIDEO+typeId, 10);
        if(ObjectUtils.isEmpty(videos))
            return new HashSet<>();
        Set<Long> ids = new HashSet<>();
        videos.forEach(item->{
            if(item!=null){
                ids.add(Long.parseLong(item.toString()));
            }
        });
        return ids;
    }
    @Override
    public void pushSystenYypeVideo(Video video) {
        redisTemplate.opsForSet().add(RedisConstant.SYSTEM_TYPE_VIDEO+video.getTypeId(),video.getId());
    }
    
    @Override
    public Collection<Long> listVideoByUserModel(Long userId) {
        //创建结果集--用来存放推荐的视频id
        Set<Long> videoids = new HashSet<>(10);
        
        if(userId!=null){
            //获取用户模型
            Map<Object,Object> map = redisUtils.hget(RedisConstant.USER_MODEL+userId);
            System.out.println("获取到的用户模型哦~~~~"+map);
            if(!ObjectUtils.isEmpty(map))
            {
                //把map换成数组-------（数组下标是概率，数组内容是对应标签）
                String[] propabilityArray= initPropabilityArray(map);
                System.out.println("转换后的概率数组哦~~~~~"+propabilityArray);
                //获取视频---随机从标签数组中获取八个标签
                Random random = new Random();
                ArrayList<String> labels = new ArrayList<>();
                //随机获取X个视频
                for (int i=0;i<8;i++){
                    String labelName = propabilityArray[random.nextInt(propabilityArray.length)];
                    labels.add(labelName);
                }
                System.out.println("随机获取的标签名称哦~~~~~"+labels);
                
                
                // 提升性能---从redis中获取数据--根据系统中的
                String t = RedisConstant.SYSTEM_STOCK;
                List<Object> list = redisTemplate.executePipelined((RedisCallback<Video>) connect -> {
                    for (String label : labels) {
                        String key = t + label;
                        connect.sRandMember(key.getBytes());
                    }
                    return null;
                });
                System.out.println("redis中你喜欢的片片哦~~~~~~"+list);
                //获取到的videoids
                List<Long> ids = list.stream().filter(Objects::nonNull).map(id -> Long.parseLong(id.toString())).collect(Collectors.toList());
                String key2 = RedisConstant.HISTORY_VIDEO;
                
                //去重-----获取以前浏览过的视频id，把这些去掉
                List simpIds = redisTemplate.executePipelined((RedisCallback<Video>) connention -> {
                    for (Long id : ids) {
                        String key = key2 + id + ":" + userId;
                        connention.get(key.getBytes());
                    }
                    return null;
                });
                simpIds =(List) simpIds.stream().filter(o -> !ObjectUtils.isEmpty(o)).collect(Collectors.toList());
                if(!ObjectUtils.isEmpty(simpIds)){
                    for(Object obj :simpIds){
                        long l = Long.parseLong(obj.toString());
                        ids.remove(l);
                    }
                }
                videoids.addAll(ids);
                System.out.println("最终你得到的片片哦~~~~~"+videoids);
                return videoids;
            }   
        }
        return null;
    }
    
    @Override
    public void pushSystemVideo(Video video) {
        System.out.println("好多好多Label哦哦哦"+video.buildLabel());
        redisTemplate.executePipelined((RedisCallback<Object>)connection->{
            for (String item : video.buildLabel()) {
                String key = RedisConstant.SYSTEM_STOCK + item;
                connection.sAdd(key.getBytes(StandardCharsets.UTF_8), String.valueOf(video.getId()).getBytes());
            }
            return null;
        });
    }

    //初始化概率数组!!!!!!!!!!!!!!!!!!!!!!!!——————将概率时间换成一个数组，随机从里面获取值！！！！！！！！！！！！！！！
    private String[] initPropabilityArray(Map<Object, Object> map) {
        Map<String,Integer> propabilityMap = new HashMap<>();
        int size = map.size();
        AtomicInteger n= new AtomicInteger();
        map.forEach((k,v)->{
            int probality = (((Double)v).intValue()+size)/size;
            n.getAndAdd(probality);
            propabilityMap.put(k.toString(), probality);
        });
        String[] probabilityArray = new String[n.get()];
        AtomicInteger index = new AtomicInteger();;
        propabilityMap.forEach((labenIds,p)->{
            int i = index.get();
            int limit = i+p;
            while(i<limit){
                probabilityArray[i++] = labenIds;
            }
                index.set(limit);
        });
        return probabilityArray;
    }
    
}
